<template>

    <!-- 背景 -->
    <div class="login-body">
        <div class="bg"></div>

        <div class="login-panel">
            <!-- ref用于校验  :rules校验规则(正则表达式) -->
            <el-form ref="formDataRef" :rules="rules" :model="formData" class="login-register" @submit.prevent>
                <div class="login-title">Pithy云盘</div>

                <!-- 邮箱 -->
                <el-form-item prop="email">
                    <el-input size="large" placeholder="请输入邮箱" v-model.trim="formData.email">
                        <!-- 输入框里的图标 -->
                        <template #prefix>
                        <span class="iconfont icon-account"></span>
                        </template>
                    </el-input>
                </el-form-item>

                <!-- 密码 <el-input> 的show-password：输入框里的尾部的眼 -->
                <el-form-item prop="password" v-if="opType == 1">
                    <el-input size="large" placeholder="请输入密码" type="password" v-model.trim="formData.password" show-password>
                        <!-- 输入框里的图标 -->
                        <template #prefix>
                        <span class="iconfont icon-password"></span>
                        </template>
                    </el-input>
                </el-form-item>


                <div v-if="opType == 0 || opType == 2">
                <!-- 邮箱验证码 -->
                <el-form-item prop="emailCode">
                    <div class="send-emali-panel">
                    <el-input size="large" placeholder="请输入邮箱验证码" v-model.trim="formData.emailCode">
                        <!-- 输入框里的图标 -->
                        <template #prefix>
                        <span class="iconfont icon-checkcode"></span>
                        </template>
                    </el-input>
                    <el-button class="send-mail-btn" @click="getEmailCode()" type="primary" size="large">获取验证码</el-button>
                    </div>
                    <!-- 文字弹窗 -->
                    <el-popover placement="left" :width="500" trigger="click">
                        <div>
                            <p>1、在垃圾箱中查找邮箱验证吗</p>
                            <p>2、在邮箱中头像->设置->反垃圾->白名单->设置邮件地址白名单</p>
                            <p>3、将邮箱【lgolgo@wentian.com】添加到白名单不知道怎么设置？</p>
                        </div>
                        <template #reference>
                            <span class="a-link" :style="{'font-size': '14px' }">
                                >未收到邮箱验证码？
                            </span>
                        </template>
                    </el-popover>
                </el-form-item>

                <!-- 昵称 -->
                <el-form-item prop="nickName" v-if="opType == 0">
                    <el-input size="large" placeholder="请输入昵称" v-model.trim="formData.nickName" maxlength="20">
                        <!-- 输入框里的图标 -->
                        <template #prefix>
                        <span class="iconfont icon-account"></span>
                        </template>
                    </el-input>
                </el-form-item>

                <!-- 密码 -->
                <el-form-item prop="registerPassword">
                    <el-input type="password" placeholder="请输入新密码" v-model.trim="formData.registerPassword" show-password>
                        <!-- 输入框里的图标 -->
                        <template #prefix>
                        <span class="iconfont icon-password"></span>
                        </template>
                    </el-input>
                </el-form-item>

                <!-- 再次输入密码 -->
                <el-form-item prop="reRegisterPassword">
                    <el-input type="password" placeholder="请再次输入密码" v-model.trim="formData.reRegisterPassword" show-password>
                        <!-- 输入框里的图标 -->
                        <template #prefix>
                        <span class="iconfont icon-password"></span>
                        </template>
                    </el-input>
                </el-form-item>
                </div>

                <!-- 图片验证码 -->
                <el-form-item prop="checkCode">
                    <div class="check-code-panel">
                        <!-- @keyup.enter: 回车触发事件 -->
                    <el-input size="large" placeholder="请输入验证码" v-model.trim="formData.checkCode" @keyup.enter="doSubmit()">
                        <!-- 输入框里的图标 -->
                        <template #prefix>
                        <span class="iconfont icon-checkcode"></span>
                        </template>
                    </el-input>
                    <img :src="checkCodeUrl" class="check-code" @click="changeCheckCode(0)" />
                    </div>
                </el-form-item>

                <!-- 登录页面选项 -->
                <el-form-item v-if="opType == 1">
                    <div class="rememberme-panel">
                        <el-checkbox v-model="formData.rememberMe">记住我</el-checkbox>
                    </div>
                    <div class="no-account">
                        <a href="javascript:void(0)" class="a-link" @click="showPanel(2)">忘记密码？</a>
                        <a href="javascript:void(0)" class="a-link" @click="showPanel(0)">没有账号？</a>
                    </div>
                </el-form-item>

                <!-- 去登录 -->
                <el-form-item v-if="opType == 2">
                    <a href="javascript:void(0)" class="a-link" @click="showPanel(1)">去登录</a>
                </el-form-item>

                <!-- 已有账号 javasciprt:void(0)-->
                <el-form-item v-if="opType == 0">
                    <a href="javascript:void(0)" class="a-link" @click="showPanel(1)">已有账号？</a>
                </el-form-item>

                <!-- 登陆按钮 -->
                <el-form-item >
                    <el-button type="primary" class="op-btn" size="large" @click="doSubmit();">
                        <span v-if="opType == 1">登陆</span>
                        <span v-if="opType == 2">重置密码</span>
                        <span v-if="opType == 0">注册</span>
                    </el-button>
                </el-form-item>

            </el-form>

        </div>

        <!-- 自定义组件：弹窗    -- main.js -- 13行 -->
        <!-- 发送邮箱验证码弹窗 -->
        <Dialog
          :show="dialogConfig4SendMailCode.show"
          :title="dialogConfig4SendMailCode.title"
          :buttons="dialogConfig4SendMailCode.buttons"
          :showCancel="false"
          width="400px"
          @close="dialogConfig4SendMailCode.show = false"
        >
          <el-form ref="formData4SendMailCodeRef" :model="formData4SendMailCode" :rules="rules" label-width="80px" @submit.prevent>
              
              <!-- 邮箱显示 -->
              <el-form-item label="邮箱">
                  {{ formData.email }}
              </el-form-item>

              <!-- 图片验证码 -->
              <el-form-item label="验证码" prop="checkCode">
                <div class="check-code-panel">
                    <el-input size="large" placeholder="请输入验证码" v-model.trim="formData4SendMailCode.checkCode">
                        <!-- 输入框里的图标 -->
                        <template #prefix>
                        <span class="iconfont icon-checkcode"></span>
                        </template>
                    </el-input>
                    <img :src="checkCodeUrl4SendMailCode" @click="changeCheckCode(1)" class="check-code" />
                </div>                   
              </el-form-item>

          </el-form>
        </Dialog>


    </div>
  
</template>

<script setup>
import { ref, reactive, getCurrentInstance, nextTick, onMounted } from "vue";
import { useRoute, useRouter } from "vue-router"
import md5 from "js-md5"

const { proxy } = getCurrentInstance();
const router = useRouter();   //用于设置值
const route = useRoute();     //用于取值

//属性定义
const formData = ref({});   //表单数据
const formDataRef = ref();  //校验
const formData4SendMailCode = ref({});   //发送邮箱验证码弹窗的参数
const formData4SendMailCodeRef = ref();  //校验
//注意：vite.config.js -- 21行中定义了域名，Request.js -- 15行定义了前缀
const api = {
    checkCode: "http://localhost:7090/api/checkCode", //图片验证码的请求地址
    sendEmailCode: "/sendEmailCode",     //邮箱验证码的请求地址
    register: "/register",               //用户注册
    login: "/login",                     //用户登录
    resetPwd: "/resetPwd"                //用户密码修改
};
const checkCodeUrl = ref(api.checkCode); //页面通用图片验证码url
const checkCodeUrl4SendMailCode = ref(api.checkCode); //“发送邮箱验证码弹窗”的图片验证码url

//“发送验证码”弹窗属性
const dialogConfig4SendMailCode = reactive({
    show: false,   //false为关闭弹窗
    title: "发送邮箱验证码",
    buttons: [
        {
          type: "primary",
          text: "发送",
          click: (e) => {
            sendEmailCode();    //发送按钮 -- 发送邮箱验证码
          },
        },
    ],
});

//在Vue3 中,onMounted 是一个生命周期钩子函数,用于在组件渲染后执行（在<script>标签头部引入）
onMounted(() => {
    restForm();      //表单重置，再判断用户上一次登录是否勾选“记住我”
})

//操作类型：0:注册 1:登录 2:修改密码
const opType = ref(1);
const showPanel = (type) => {
    opType.value = type;
    restForm();       //表单重置
};

//判断前后两次输入的密码是否相同
const checkRePassword = (rule, value, callback) => {
    if (value !== formData.value.registerPassword) {
        callback(new Error(rule.message));
    } else {
        callback();
    }
};
//根据form表单中的prop属性进行选择校验（proxy.Verify已在main.js中声明）
const rules = {
    email: [             //邮箱校验
        { required: true, message:"邮箱不能为空" },
        { validator: proxy.Verify.email, message:"请输入正确的邮箱" },
    ],
    registerPassword: [  //设置密码校验
        { required: true, message:"密码不能为空" },
        { validator: proxy.Verify.password, message:"密码须为8~18位，由数字、字母和特殊字符组成" },
    ],
    reRegisterPassword: [//再次设置密码校验
        { required: true, message:"密码不能为空" },
        { validator: checkRePassword, message:"两次输入的密码不一致" },
    ],
    //密码校验
    password: [ { required: true, message:"密码不能为空" } ],
    //邮箱验证码校验
    emailCode: [ { required: true, message:"验证码不能为空" } ],
    //昵称校验
    nickName: [ { required: true, message:"昵称不能为空" } ],
    //图片验证码校验
    checkCode: [ { required: true, message:"验证码不能为空" } ]
};

//点击验证码图片刷新
const changeCheckCode = (type) => {
    if (type == 0) {
        //传递的参数为0，则刷新页面的图片
        checkCodeUrl.value = api.checkCode + "?type=" + type + "&time=" + new Date().getTime();
    } else {
        //否，则刷新“发送邮箱验证码弹窗”的图片
        checkCodeUrl4SendMailCode.value = api.checkCode + "?type=" + type + "&time=" + new Date().getTime();
    }
};

//"获取验证码"按钮
const getEmailCode = () => {
    //调用rules.email校验邮箱格式
    formDataRef.value.validateField("email", (valid) => {
        if (!valid) {
            return;
        }
        dialogConfig4SendMailCode.show = true   //打开弹窗
        //清空表单数据
        nextTick(() => {
            changeCheckCode(1);   //刷新图片验证码
            formData4SendMailCodeRef.value.resetFields(); //对整个表单进行重置，并移除校验结果
            formData4SendMailCode.value = {
                email: formData.value.email
            }
        })
    });
};

//发送按钮 -- 发送邮箱验证码
const sendEmailCode = () => {
    formData4SendMailCodeRef.value.validate(async (valid) => {  //校验表单
        if (!valid) {
            return;
        };
        const params = Object.assign({}, formData4SendMailCode.value); //封装请求参数
        params.type = opType.value == 0 ? 0 : 1;   //0:注册  1:修改密码
        //发送请求 -- 获得邮箱验证码
        let result = await proxy.Request({ 
            url: api.sendEmailCode,
            params: params,
            errorCallback: () => {    //验证码错误则刷新图片
                changeCheckCode(1);
            }
        });
        //判断请求结果
        if (!result) {
            return;
        } 
        proxy.Message.success("验证码发送成功，请登陆邮箱查看");
        dialogConfig4SendMailCode.show = false;    //关闭弹窗
    });
};

//表单重置
const restForm = () => {
    changeCheckCode(0);              //刷新图片验证码
    formDataRef.value.resetFields(); //对整个表单进行重置，并移除校验结果
    formData.value = {};             //表单重置
    if (opType.value == 1) {         //如果当前为登录页面，再判断用户上一次登录是否勾选“记住我”
        const cookieLoginInfo = proxy.VueCookies.get("loginInfo");
        if (cookieLoginInfo) {      
            formData.value = cookieLoginInfo;
        }
    }

};

//表单提交（proxy.Request、proxy.VueCookies已在main.js中声明）
const doSubmit = () => {
    formDataRef.value.validate(async (valid) => {   //校验表单
        if (!valid) {
            return;
        }
        
        //请求注册
        if (opType.value == 0) {
            let result = await proxy.Request({
               url: api.register,
                params: formData.value,
                dataType: 'json',         //以json形式发送参数（默认是以文件形式）如不设置dataType，则后端无需使用@RequestBody接收对象
                errorCallback: () => {    //验证码错误则刷新图片
                    changeCheckCode(0);
                }
            });
            proxy.Message.success("注册成功，请登录");
            showPanel(1);
        }

        //请求登录
        if (opType.value == 1) { 
            //判断用户上一次登录是否勾选“记住我”，如未勾选或密码不一致，则将密码加密
            //如已勾选“记住我”，则在上面的restForm方法中设置formData           
            let cookieLoginInfo = proxy.VueCookies.get("loginInfo");
            let cookiePassword = cookieLoginInfo == null ? null : cookieLoginInfo.password;
            if (formData.value.password !== cookiePassword) {
                console.log("login.vue:364:加密--" + formData.value.password);
                formData.value.password = md5(formData.value.password);   //md5在<script>标签头部引入
            }
            //请求发送
            let result = await proxy.Request({
                url: api.login,
                params: formData.value,
                //dataType: 'json',         //以json形式发送参数（默认是以文件形式）如不设置dataType，则后端无需使用@RequestBody接收对象
                errorCallback: () => {    //验证码错误则刷新图片
                    changeCheckCode(0);
                }
            });
            //判断用户此次提交是否勾选“记住我”
            if (formData.value.rememberMe) {    
                const loginInfo = {    
                    email: formData.value.email,
                    password: formData.value.password,
                    rememberMe: formData.value.rememberMe
                };
                proxy.VueCookies.set("loginInfo", loginInfo, "7d");  //将登陆账号保存为cookie，存活时间为7天
            } else {
                proxy.VueCookies.remove("loginInfo");                //未勾选则删除cookie
            }
            proxy.Message.success("欢迎使用pithypan");
            //处理返回结果
            const userInfo = result.data.userInfo;
            proxy.VueCookies.set("userInfo", userInfo, 0); //将登录用户保存为cookie，0为关闭浏览器删除
            const redirectUrl = route.query.redirectUrl || "/";  //route.query: 从url ?号后面获取记录着的地址
            router.push(redirectUrl);                            //跳转
        }

        //请求密码修改 
        if (opType.value == 2) {
            let result = await proxy.Request({
                url: api.resetPwd,
                params: formData.value,
                dataType: 'json',         //以json形式发送参数（默认是以文件形式）如不设置dataType，则后端无需使用@RequestBody接收对象
                errorCallback: () => {    //验证码错误则刷新图片
                    changeCheckCode(0);
                }
            });
            proxy.Message.success("重置密码成功，请登录");
            showPanel(1);
        }

        // let result = await proxy.Request({
        //     url: api.register,
        //     params: formData.value,
        //     dataType: 'json',//以json形式发送参数（默认是以文件形式）如不设置dataType，则后端无需使用@RequestBody接收对象
        //     errorCallback: () => {    //验证码错误则刷新图片
        //         changeCheckCode(0);
        //     }
        // });
        // console.log(result);
        // proxy.Message.success("欢迎使用pithypan");
    });
}

</script>

<style lang="scss" scoped>
//     在vue中:Ap.vue相当于根容器,不设置 scoped。所以一般在App.vue中引用公共样式。
// 而在其它.vue页面中用 scoped,代表当前样式只作用于当前vue页面。不作用于其它.vue页面。

.login-body {
    height: calc(100vh);
    background-size: cover;
    background: url("../assets/login_bg.jpg");
    display: flex;

    .bg {
        flex: 1;
        background-size: cover;
        background-position: center;
        background-size: 500px;
        background-repeat: no-repeat;
        background-image: url("../assets/login_img2.png");
    }

    .login-panel {
        width: 330px;
        margin-right: 15%;
        margin-top: calc((100vh - 500px) / 2);
        .login-register {
            padding: 25px;
            background: #fff;
            border-radius: 5px;
            .login-title {
                text-align: center;
                font-size: 18px;
                font-weight: bold;
                margin-bottom: 20px;
            }
            .send-emali-panel {
                display: flex;
                width: 100%;
                justify-content: space-between;
                .send-mail-btn {
                    margin-left: 5px;
                }
            }
            .rememberme-panel {
                width: 100%;
            }
            .no-account {
                width: 100%;
                display: flex;
                justify-content: space-between;
            }
            .op-btn {
                width: 100%;
            }
        }
    }

    .check-code-panel {
        width: 100%;
        display: flex;
        .check-code {
            margin-left: 5px;
            cursor: pointer;
        }
    }

    .login-btn-qq {
        margin-top: 20px;
        text-align: center;
        display: flex;
        align-items: center;
        justify-content: center;
        img {
            cursor: pointer;
            margin-left: 10px;
            width: 20px;
        }
    }
}

</style>